ostree/deploy: Test finalization locking
authorJonathan Lebon <jonathan@jlebon.com>
Fri, 21 Jan 2022 18:47:02 +0000 (13:47 -0500)
committerJonathan Lebon <jonathan@jlebon.com>
Fri, 21 Jan 2022 18:48:35 +0000 (13:48 -0500)
Support for that file was added previously, but the testing lived in
rpm-ostree only. Let's add it here too.

In the process add a hidden `--lock-finalization` to `ostree admin
deploy` to make testing easier (though it could also be useful to update
managers driving OSTree via the CLI).

src/ostree/ot-admin-builtin-deploy.c
tests/kolainst/destructive/staged-deploy.sh

index 97351b14408f18aa653a5c0332254654e8e378c2..d4743890e0245d2128c91562fe852892de0bbb15 100644 (file)
@@ -21,6 +21,8 @@
 
 #include "config.h"
 
+#include "ostree-sysroot-private.h"
+
 #include "ot-main.h"
 #include "ot-admin-builtins.h"
 #include "ot-admin-functions.h"
@@ -31,6 +33,7 @@
 
 static gboolean opt_retain;
 static gboolean opt_stage;
+static gboolean opt_lock_finalization;
 static gboolean opt_retain_pending;
 static gboolean opt_retain_rollback;
 static gboolean opt_not_as_default;
@@ -51,6 +54,7 @@ static GOptionEntry options[] = {
   { "no-merge", 0, 0, G_OPTION_ARG_NONE, &opt_no_merge, "Do not apply configuration (/etc and kernel arguments) from booted deployment", NULL},
   { "retain", 0, 0, G_OPTION_ARG_NONE, &opt_retain, "Do not delete previous deployments", NULL },
   { "stage", 0, 0, G_OPTION_ARG_NONE, &opt_stage, "Complete deployment at OS shutdown", NULL },
+  { "lock-finalization", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &opt_lock_finalization, "Prevent automatic deployment finalization on shutdown", NULL },
   { "retain-pending", 0, 0, G_OPTION_ARG_NONE, &opt_retain_pending, "Do not delete pending deployments", NULL },
   { "retain-rollback", 0, 0, G_OPTION_ARG_NONE, &opt_retain_rollback, "Do not delete rollback deployments", NULL },
   { "not-as-default", 0, 0, G_OPTION_ARG_NONE, &opt_not_as_default, "Append rather than prepend new deployment", NULL },
@@ -202,6 +206,20 @@ ot_admin_builtin_deploy (int argc, char **argv, OstreeCommandInvocation *invocat
         return glnx_throw (error, "--stage cannot currently be combined with --retain arguments");
       if (opt_not_as_default)
         return glnx_throw (error, "--stage cannot currently be combined with --not-as-default");
+      /* touch file *before* we stage to avoid races */
+      if (opt_lock_finalization)
+        {
+          if (!glnx_shutil_mkdir_p_at (AT_FDCWD,
+                                       dirname (strdupa (_OSTREE_SYSROOT_RUNSTATE_STAGED_LOCKED)),
+                                       0755, cancellable, error))
+            return FALSE;
+
+          glnx_autofd int fd = open (_OSTREE_SYSROOT_RUNSTATE_STAGED_LOCKED,
+                                     O_CREAT | O_WRONLY | O_NOCTTY | O_CLOEXEC, 0640);
+          if (fd == -1)
+            return glnx_throw_errno_prefix (error, "touch(%s)",
+                                            _OSTREE_SYSROOT_RUNSTATE_STAGED_LOCKED);
+        }
       /* use old API if we can to exercise it in CI */
       if (!overlay_initrd_chksums)
         {
index baadb3d86ebc6175796eeaeb76f0c8f3aa75fe7a..406911ca6e84b6c6e354c233ea74dfcfd1678051 100755 (executable)
@@ -78,10 +78,18 @@ EOF
     # And there should not be a staged deployment
     test '!' -f /run/ostree/staged-deployment
 
-    # Upgrade with staging
     test '!' -f /run/ostree/staged-deployment
-    ostree admin deploy --stage staged-deploy
+    ostree admin deploy --stage staged-deploy --lock-finalization
     test -f /run/ostree/staged-deployment
+    test -f /run/ostree/staged-deployment-locked
+    # check that we can cleanup the staged deployment
+    ostree admin undeploy 0
+    test ! -f /run/ostree/staged-deployment
+    test ! -f /run/ostree/staged-deployment-locked
+    echo "ok cleanup staged"
+
+    # Upgrade with staging
+    ostree admin deploy --stage staged-deploy
     origcommit=$(ostree rev-parse staged-deploy)
     cd /ostree/repo/tmp
     ostree checkout -H "${origcommit}" t